package pers.cj.pdos.controller;


import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import pers.cj.pdos.controller.base.BaseController;
import pers.cj.pdos.controller.entity.ResponseData;
import pers.cj.pdos.controller.entity.ResponseEntity;
import pers.cj.pdos.controller.entity.ResponseList;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.excel.ExcelInGoodsRefund;
import pers.cj.pdos.service.*;
import pers.cj.pdos.task.CleanTempExcelTask;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author chenj
 * @since 2019-11-04
 */
@Controller
@RequestMapping("/inGoods")
public class InGoodsRefundController extends BaseController {
    @Autowired
    IInGoodsRefundService inGoodsRefundService;
    @Autowired
    IHouseOutService houseOutService;
    @Autowired
    IGoodsStockService goodsStockService;
    @Autowired
    IGoodsService goodsService;
    @Autowired
    IGoodsCostService goodsCostService;

    @RequiresPermissions("inGoodsRefund:query")
    @RequestMapping("/inGoodsRefund")
    public String inGoods(Model model) {
        model.addAttribute(getBusinessSet());
        return "inGoodsRefund/inGoodsRefund";
    }


    @RequiresPermissions("inGoodsRefund:insert")
    @RequestMapping("/inGoodsRefundNew")
    public String inGoodsNew(){
        return "/inGoodsRefund/inGoodsRefundNew";
    }

    @RequiresPermissions("inGoodsRefund:query")
    @RequestMapping("/inGoodsRefundDetail")
    public String inGoodsDetail(Model model, String id){
        model.addAttribute("id",id);
        return "/inGoodsRefund/inGoodsRefundDetail";
    }

    @ResponseBody
    @RequestMapping("/inGoodsRefund/getList")
    public ResponseList getList(int page,
                                int limit,
                                String close,
                                String search,
                                String no,
                                String goodsName,
                                String remark,
                                String provider,
                                String makeTime1,
                                String makeTime2,
                                String storeId,
                                String userId,
                                String date1,
                                String date2,
                                String date,
                                String providerId,
                                String houseId,
                                String makeUserId){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<InGoodsRefundVo> list = inGoodsRefundService.listVo(company.getId(),
                page,
                limit,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                providerId,
                houseId,
                makeUserId);
        long count = inGoodsRefundService.count(company.getId(),
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                providerId,
                houseId,
                makeUserId);
        return ResponseList.success(count,list);
    }



    @ResponseBody
    @RequiresPermissions("inGoodsRefund:insert")
    @RequestMapping("/inGoodsRefund/add")
    public ResponseEntity add(@RequestBody InGoodsRefundVo inGoodsRefundVo){
        Company company = getCompany();
        BusinessSet businessSet = getBusinessSet();



        if (Utils.isEmpty(inGoodsRefundVo.getNo())){
            return ResponseEntity.fail("编号不能为空");
        }

        if (Utils.isEmpty(inGoodsRefundVo.getInGoodsRefundGoodsVoList())){
            return ResponseEntity.fail("您未选择任何商品");
        }

        if (inGoodsRefundVo.getDate() == null){
            return ResponseEntity.fail("业务日期不能为空");
        }

        if (inGoodsRefundVo.getTotalAmt().compareTo(inGoodsRefundVo.getRealAmt()) == -1){
            return ResponseEntity.fail("应退金额不能大于总计金额");
        }

        if (inGoodsRefundService.checkNo(inGoodsRefundVo.getNo(),company.getId())){
            return ResponseEntity.fail("编号已被使用");
        }
        
        if (getHouseLocking(inGoodsRefundVo.getHouseId())) {
            return ResponseEntity.fail("仓库被锁定，请更换仓库");
        }

        GoodsUtil goodsUtil = new GoodsUtil(inGoodsRefundVo.getHouseId(), inGoodsRefundVo.getInGoodsRefundGoodsVoList());
        if (!PdosUtils.houseInOut(businessSet)) {
            String msg = goodsUtil.checkStock();
            if (msg!=null){
                return ResponseEntity.fail(msg);
            }
        }


        InGoodsRefund inGoodsRefund = DataUtil.genEntityFromVo(InGoodsRefund.class, inGoodsRefundVo);
        DataUtil.processEntity(company,inGoodsRefund);
        inGoodsRefund.setMakeUserId(getLoginUserId());
        inGoodsRefund.setMakeTime(new Date());
        inGoodsRefund.setClose(false);
        if (Utils.isEmpty(inGoodsRefund.getInGoodsId())) {
            inGoodsRefund.setInGoodsId(null);
        }
        if (!PdosUtils.houseInOut(businessSet)) {
            inGoodsRefund.setStatus(1);
        } else {
            inGoodsRefund.setStatus(2);
        }

        inGoodsRefund.setOldTotalAmt(goodsUtil.getTotalAmount());

        if(!PdosUtils.inTaxRateFlag(businessSet)) {
            inGoodsRefund.setTax(new BigDecimal(0));
        } else {
            inGoodsRefund.setTax(inGoodsRefund.getOldTotalAmt().multiply(PdosUtils.inTaxRate(businessSet)));
        }


        List<GoodsCost> list = goodsCostService.listByGoodsList(inGoodsRefundVo.getInGoodsRefundGoodsVoList());
        Map<String,GoodsCost> map = DataUtil.genMap("goodsId", list);

        BigDecimal totalCost = new BigDecimal(0);

        List<InGoodsRefundGoods> inGoodsRefundGoodsList = new ArrayList<>();
        List<GoodsSn> goodsSnList = new ArrayList<>();
        List<GoodsSnLog> goodsSnLogList = new ArrayList<>();
        for (InGoodsRefundGoodsVo vo:inGoodsRefundVo.getInGoodsRefundGoodsVoList()) {
            InGoodsRefundGoods entity = DataUtil.genEntityFromVo(InGoodsRefundGoods.class, vo);
            DataUtil.processEntity(company,entity);
            entity.setInGoodsRefundId(inGoodsRefund.getId());
            if(!PdosUtils.inTaxRateFlag(businessSet)) {
                entity.setTax(new BigDecimal(0));
            } else {
                entity.setTax(entity.getAmount().multiply(PdosUtils.inTaxRate(businessSet)));
            }

            if (map.containsKey(entity.getGoodsId())) {
                entity.setCost(map.get(entity.getGoodsId()).getCost());
                totalCost = totalCost.add(entity.getCost().multiply(entity.getTimes().multiply(entity.getNumber())));
            } else {
                entity.setCost(new BigDecimal(0));
            }
            inGoodsRefundGoodsList.add(entity);

            if (!Utils.isEmpty(vo.getGoodsSnList())){
                for (GoodsSn goodsSn : vo.getGoodsSnList()) {
                    goodsSnList.add(goodsSn);

                    GoodsSnLog log = new GoodsSnLog();
                    DataUtil.processEntity(company,log);
                    log.setGoodsId(goodsSn.getGoodsId());
                    log.setSn(goodsSn.getSn());
                    log.setType(5);
                    log.setInGoodsRefundGoodsId(entity.getId());
                    goodsSnLogList.add(log);
                }
            }
        }

        inGoodsRefund.setDiffAmount(totalCost.subtract(inGoodsRefund.getOldTotalAmt()));

        inGoodsRefundService.insert(businessSet, inGoodsRefund,inGoodsRefundGoodsList, goodsSnList,goodsSnLogList);

        if (!Utils.isEmpty(goodsSnList) && PdosUtils.houseInOut(businessSet)) {
            //已启用待出库入管理，但是前台传入了sn号，提示
            return ResponseEntity.success("处理成功，管理员在您新增单据过程中启用了出入库管理，录入的sn需要在出库时重新选择");
        }
        return ResponseEntity.success();
    }

    @ResponseBody
    @RequiresPermissions("inGoodsRefund:close")
    @RequestMapping("/inGoodsRefund/close")
    public ResponseEntity close(@RequestBody InGoodsRefund inGoodsRefund){
        //检查是否已经关闭
        if (inGoodsRefundService.checkClose(inGoodsRefund)){
            return ResponseEntity.fail("该单据已被关闭，不能重复关闭");
        }


        if(houseOutService.checkByLinkId(inGoodsRefund.getId())) {
            return ResponseEntity.fail("该订单存在出库单，请先作废对应的出库单");
        }

        try {
            inGoodsRefundService.close(inGoodsRefund, getBusinessSet());
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("关闭订单失败");
        }
    }

    @ResponseBody
    @RequestMapping(value = "/inGoodsRefund/uploadImg", method = RequestMethod.POST)
    public ResponseData uploadImg(MultipartFile imageFile) {
        return processUploadImg(imageFile, "inGoodsRefund");
    }

    @ResponseBody
    @RequiresPermissions("inGoodsRefund:insert")
    @RequestMapping("/inGoodsRefund/updateImage")
    public ResponseEntity updateImage(@RequestBody InGoodsRefund inGoodsRefund){
        try {
            InGoodsRefund temp = new InGoodsRefund();
            temp.setId(inGoodsRefund.getId());
            temp.setImage(inGoodsRefund.getImage());
            inGoodsRefundService.updateById(temp);
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("更新图片失败");
        }
    }


    @ResponseBody
    @RequestMapping("/inGoodsRefund/getVoById")
    public ResponseData getVoById(String id) {
        return ResponseData.success(inGoodsRefundService.getVoById(id));
    }


    @ResponseBody
    @RequiresPermissions("inGoodsRefund:export")
    @RequestMapping("/inGoodsRefund/export")
    public ResponseData export(String close,
                               String search,
                               String no,
                               String goodsName,
                               String remark,
                               String provider,
                               String makeTime1,
                               String makeTime2,
                               String storeId,
                               String userId,
                               String date1,
                               String date2,
                               String date,
                               String providerId,
                               String houseId,
                               String makeUserId){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<InGoodsRefundVo> list = inGoodsRefundService.listVo(company.getId(),
                null,
                null,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                providerId,
                houseId,
                makeUserId);

        String fileName = "进货退货单列表" + DateUtils.getDate(new Date(), DateUtils.YYYYMMDDHHMMSSSS) + ".xlsx";
        try {
            String path = FileProperUtil.getInstance().getVal("excel.temp");
            OutputStream out = new FileOutputStream(path+fileName);
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,true);
            Sheet sheet1 = new Sheet(1,0, ExcelInGoodsRefund.class);
            sheet1.setSheetName("进货退货单信息");
            writer.write(genExcelList(list), sheet1);
            writer.finish();
            out.close();
            CleanTempExcelTask.put(fileName,new Date().getTime());
            return ResponseData.success(fileName);
        } catch (IOException e) {
            return ResponseData.fail("订单列表导出失败");
        }
    }

    private List<ExcelInGoodsRefund> genExcelList(List<InGoodsRefundVo> inGoodsRefundVoList) {
        List<ExcelInGoodsRefund> list = new ArrayList<>();
        BusinessSet businessSet = getBusinessSet();
        for (InGoodsRefundVo vo : inGoodsRefundVoList){
            ExcelInGoodsRefund excel = new ExcelInGoodsRefund();
            excel.setDate(DateUtils.getDate(vo.getDate(), DateUtils.YYYY_MM_DD));
            excel.setNo(vo.getNo());

            if (vo.getInGoods() == null){
                excel.setInGoodsNo("");
            }else {
                excel.setInGoodsNo(vo.getInGoods().getNo());
            }
            excel.setProvider(vo.getProvider().getName());
            String goods = "";
            BigDecimal number = new BigDecimal(0);
            for (InGoodsRefundGoodsVo inGoodsRefundGoodsVo : vo.getInGoodsRefundGoodsVoList()){
                number = number.add(inGoodsRefundGoodsVo.getNumber());
                goods += inGoodsRefundGoodsVo.getGoodsVo().getName() + "、";
            }
            excel.setGoods(goods);
            excel.setNumber(PdosUtils.getNumber(number,businessSet));
            excel.setTotalAmt(PdosUtils.getPrice(vo.getTotalAmt(),businessSet));
            excel.setRealAmt(PdosUtils.getPrice(vo.getRealAmt(),businessSet));
            excel.setStore(vo.getHouseVo().getStore().getName());
            excel.setHouse(vo.getHouseVo().getName());
            excel.setUser(vo.getUser().getName());
            excel.setMakeUser(vo.getMakeUser().getName());
            excel.setRemark(vo.getRemark());
            excel.setClose(vo.getClose() ? "是":"否");
            list.add(excel);
        }
        return list;
    }
}
